package org.nlp2rdf.navigator.server.tiger;

import java.io.File;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.MultiHashMap;
import org.apache.commons.collections.MultiMap;
import org.apache.log4j.Logger;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;

public class Closure {
	private static final Logger logger = Logger.getLogger(Closure.class);

	OntModel ont;
	static String defaultxmlFile = "files/tiger.noSchema.noImports.rdf";
	static String filter = Config.prefix;
	static boolean useFilter = false;
	static boolean includeClass = false;
	
 
	public static void main(String[] args) {
		MultiMap result = compute();
		for(Object s : result.keySet()){
			System.out.println(s);
			System.out.println(result.get(s));
		}
		Map<String, String> result2 = makeFilter();
		for(String s : result2.keySet()){
			System.out.println(s);
			System.out.println(result2.get(s));
		}
	}
	
	@SuppressWarnings("unchecked")
	public static Map<String, String> makeFilter(){
		MultiMap mhm = compute();
		Map<String, String> result = new HashMap<String, String>();
		for(Object s : mhm.keySet()){
			List<String> current = (List<String>) mhm.get(s);
			StringBuffer one= new StringBuffer();
			if(includeClass){
				one.append("<"+((String)s)+">, ");
			}
			int i=0;
			for(;i<current.size()-1;i++){
				one.append("<"+current.get(i)+">, ");
			}
			one.append("<"+current.get(i)+"> ");
			
			result.put((String)s,one.toString() );
		}
		logger.debug("Computed subclass expansion for "+defaultxmlFile+ " with "+result.keySet().size()+" classes ");
		return result;
	}
	
	public static MultiMap compute(){
		return compute(defaultxmlFile);
	}
	public static MultiMap compute(String xmlFile){
		
		OntModel ont = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM, ModelFactory.createDefaultModel());
		MultiMap unfiltered = new MultiHashMap();
		MultiMap filtered = new MultiHashMap();
		
		try {
			ont.read(new File(xmlFile).toURI().toURL().toString());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		
		for(OntClass cl:ont.listClasses().toList()){
			if(cl.isAnon()){
				continue;
			}
			
			Set<OntClass> s = transitiveClosure(cl);
			for(OntClass subs : s){
				if(subs.getURI().startsWith(filter)){
					filtered.put(cl.getURI(),subs.getURI() );
				}
				unfiltered.put(cl.getURI(),subs.getURI() );
				
			}
		}
		
		return (useFilter)?filtered:unfiltered;
		
	}
	
	private static Set<OntClass> transitiveClosure(OntClass c){
		Set<OntClass> initial = c.listSubClasses(true).toSet();
		if(initial.isEmpty()){
//			System.out.println(c.getURI());
		}
		
		boolean expanded = true;
		while(expanded){
			expanded = false;
			for(OntClass one:c.listSubClasses(true).toSet()){
				if(initial.add(one)){
					expanded = true;
				}
			}
		}
		return initial;
	}
	
}
